package com.platform.qujia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.platform.qujia.constantEnum.DecimalConstant;
import com.platform.qujia.dao.PayOrderMapper;
import com.platform.qujia.enums.WxTemplateEnum;
import com.platform.qujia.param.request.MultiplePayInfoReq;
import com.platform.qujia.param.request.OrderPayInfo;
import com.platform.qujia.pay.strategy.YunhuaChannel;
import com.platform.qujia.pojo.*;
import com.platform.qujia.pojo.dto.DivideAccountsSettingDto;
import com.platform.qujia.service.*;
import com.platform.qujia.utils.LocalDateTimeUtil;
import com.platform.qujia.utils.MobilePhoneUtil;
import com.platform.qujia.utils.exception.CustomException;
import com.platform.qujia.utils.exception.EndingException;
import com.platform.qujia.utils.sxfpay.SXFPayParam;
import com.platform.qujia.utils.sxfpay.SXFPayUtil;
import com.platform.qujia.utils.weixinapp.WxPushUtil;
import com.platform.qujia.utils.yunHua.YunHuaParam;
import com.platform.qujia.utils.yunHua.yunHuaPayUtils;
import com.yunhua.oil.common.core.utils.LocalDateUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @date 2024/1/29
 */
@Service
public class QujiaPayV2ServiceImpl implements QujiaPayV2Service {
    private static final Logger log = LoggerFactory.getLogger(QujiaPayV2ServiceImpl.class);


    @Autowired
    private PayOrderService payOrderService;
    @Autowired
    private PayOrderMapper payOrderMapper;
    @Autowired
    private AppUserInfoService appUserInfoService;
    @Autowired
    private EnterpriseService enterpriseService;
    @Autowired
    private IUnitePayOrderService unitePayOrderService;
    @Autowired
    private IUnitePayOrderRelService unitePayOrderRelService;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Value("${qujia.domainName}")
    private String domainName;

    @Value("${qujia.yunhuaPayUrl}")
    private String yunhuaPayUrl;
    @Value("${qujia.yunhuaPrePayUrl}")
    private String yunHuaPrePayUrl;
    @Autowired
    private GzhNewsTemplateService gzhNewsTemplateService;
    @Autowired
    private WxPushUtil wxPushUtil;
    @Autowired
    private ElectronicMembershipCardService electronicMembershipCardService;

    @Override
    @Transactional
    public Map<String, Object> toMultipleThirdPay(MultiplePayInfoReq multiplePayInfoReq){
        log.info("拉起支付参数payInfoRequest{}", multiplePayInfoReq.toString());
        try {
            if (StringUtils.isBlank(multiplePayInfoReq.getStationId()) || multiplePayInfoReq.getOrderList() == null || CollectionUtils.isEmpty(multiplePayInfoReq.getOrderList())) {
                throw new EndingException("缺少必传参数");
            }
            if (StringUtils.isBlank(multiplePayInfoReq.getOpenId()) && StringUtils.isBlank(multiplePayInfoReq.getAliUserId())) {
                throw new EndingException("缺少用户参数");
            }

            String stationId = multiplePayInfoReq.getStationId();
            String openId = "";
            Integer consumerId = 0;
            Integer enterpriseId = 0;
            Long enterpriseIdLong = 0L;
            String payType = "";
            String orderOriginType = "";
            BigDecimal amt = BigDecimal.ZERO;
            List<OrderPayInfo> orderList = multiplePayInfoReq.getOrderList();
            for (OrderPayInfo orderPayInfo : orderList) {
                PayOrder payOrder = payOrderService.selectOrderInfoByOrdNo(orderPayInfo.getOrdNo());
                if (payOrder == null) {
                    throw new EndingException("查无此单");
                }
                if (!StringUtils.equals("0",payOrder.getStatus())) {
                    throw new EndingException("订单状态不对");
                }
                consumerId = payOrder.getConsumerId();
                payType = payOrder.getPayType();
                enterpriseId = payOrder.getEnterpriseId();
                enterpriseIdLong = Long.valueOf(enterpriseId);
                orderOriginType = payOrder.getOrderOriginType();
                BigDecimal orderAmt = BigDecimal.valueOf(payOrder.getAmt());
                amt = amt.add(orderAmt);

            }



            Enterprise enterprise = enterpriseService.selectEnterpriseInfo(enterpriseId);
//            String payType = payOrder.getPayType();       //用户类型：1、微信；2、支付宝；
//            String orderOriginType = payOrder.getOrderOriginType();     //订单来源：1、微信小程序；2、微信公众号；3、支付宝小程序；4、支付宝公众号；
            //获取油站的支付配置项信息
            String payType_num = "";
            PayWay payWay = new PayWay();
            payWay.setStationId(Integer.valueOf(stationId));
            String payAppId = "";
            if ("wx".equals(payType)) {
                if ("1".equals(orderOriginType)) {
                    payAppId = enterprise.getAppId();
                }
                if ("2".equals(orderOriginType)) {
                    payAppId = enterprise.getGzhAppId();
                }
            }

            switch (payType) {
                case "wx":   //微信
                    payType_num = "1";
                    openId = multiplePayInfoReq.getOpenId();
                    break;
                case "zfb":  //支付宝
                    payType_num = "2";
                    openId = multiplePayInfoReq.getAliUserId();
                    break;
                case "yl":   //银联
                    payType_num = "3";
                    break;
            }

            payWay.setAppType(payType_num);        //支付宝还是微信
            payWay.setUseType("1");             //使用类型
            List<PayWay> payWayList = enterpriseService.selectStaPayWay(payWay); //获取该油站的支付类型
            HashMap<String, Object> resultMap = new HashMap<>();
            if (payWayList == null && payWayList.size() != 1) {
                throw new EndingException("支付渠道数目不对");
            }
            PayWay payWay1 = payWayList.get(0);
            String orderNo = com.platform.qujia.utils.StringUtils.generateOrdNo();
            UnitePayOrder unitePayOrder = new UnitePayOrder();
            unitePayOrder.setEnterpriseId(enterpriseIdLong);
            unitePayOrder.setStationId(Long.valueOf(stationId));
            unitePayOrder.setUniteOrderNo(orderNo);
            unitePayOrder.setStatus("0");
            unitePayOrder.setAmt(amt);
            unitePayOrder.setServiceCharge(payWay1.getServiceCharge());
            unitePayOrder.setCommission(amt.multiply(payWay1.getServiceCharge()).multiply(DecimalConstant.O_001).setScale(2, RoundingMode.HALF_UP));
            unitePayOrder.setPayWayId(Long.valueOf(payWay1.getPayWayId()));
            unitePayOrder.setCreateTime(LocalDateTime.now());
            unitePayOrderService.save(unitePayOrder);
            ArrayList<UnitePayOrderRel> unitePayOrderRels = new ArrayList<>(orderList.size());
            for (OrderPayInfo orderPayInfo : orderList) {
                UnitePayOrderRel orderRel = new UnitePayOrderRel();
                orderRel.setEnterpriseId(enterpriseIdLong);
                orderRel.setUniteOrderNo(orderNo);
                orderRel.setOrderNo(orderPayInfo.getOrdNo());
                unitePayOrderRels.add(orderRel);
            }
            unitePayOrderRelService.saveBatch(unitePayOrderRels);


            /*String userId="";
            List<AppUserInfo>appUserInfos=appUserInfoService.selectAppUserInfoByMobilePhoneAndStationId(AppUserInfo.builder().mobilePhone(payOrder.getCustomerPhone()).stationId(payOrder.getEnterpriseId()).build());
           if(appUserInfos!=null&&appUserInfos.size()>0){
               if(appUserInfos.get(0).getYunhuaUserId()!=null){
                   userId=appUserInfos.get(0).getYunhuaUserId();
               }else {
                   userId=appUserInfos.get(0).getMobilePhone();
               }
           }*/
            AppUserInfo appUserInfo = appUserInfoService.getById(consumerId);
            String userId = null;
            if (StringUtils.isNotBlank(appUserInfo.getYunhuaUserId())) {
                userId = appUserInfo.getYunhuaUserId();
            } else if (!MobilePhoneUtil.isFakePhone(appUserInfo.getMobilePhone())) {
                userId = appUserInfo.getMobilePhone();
            } else {
                userId = YunhuaChannel.DEFAULT_USER_ID;
            }
            PayOrder p = new PayOrder();                            //更新订单参数
            //String amt = payOrder.getAmt().toString();              //订单实付金额

            // 优惠券逻辑
//            if (!MobilePhoneUtil.isFakePhone(payOrder.getCustomerPhone()) && StringUtils.isNotBlank(payInfoRequest.getCouponUserId())) {
//                log.info("/toThirdPay-CouponUserId：" + payInfoRequest.getCouponUserId());
//
//                Station station = enterpriseService.selectStationById(Integer.valueOf(payOrder.getStationId()));
//
//                //计算使用优惠券后传参优惠券ID
//                payOrder.setDiscountCoupon(payInfoRequest.getCouponUserId());
//                //计算优惠券
//                CouponUser couponUser = reductionActivityService.checkCoupon(appUserInfo, payOrder, station);
//
//                if (couponUser != null) {
//                    //使用优惠券时要更新的订单信息
//                    //amt = couponUser.getNewAmtByCoupon().toString();
//                    p.setDiscountCoupon(payInfoRequest.getCouponUserId());
//                    p.setDiscountCouponAmt(payOrder.getReceivableAmt() - payOrder.getAmt() - payOrder.getDiscountAmt());
//
//                }
//
//            }

            String payTypeSta = payWay1.getPayType();     //第三方支付类型
            String mno = payWay1.getMno();                //商户号
//            String subject = payOrder.getOilName() + " - " + payOrder.getStationName();
            String subject = "柴油"; // todo
            String appId = payWay1.getEnterprise().getAppId();
            String notifyUrl = "";
            String weChatType = "2";
            if (multiplePayInfoReq.getPayAppType() != null && !"".equals(multiplePayInfoReq.getPayAppType()) && "1".equals(multiplePayInfoReq.getPayAppType())) {
                weChatType = "1";
            }

            log.info("wetchatType---------------------------" + weChatType);
            switch (payTypeSta) {
                case "1":   //随行付
                    notifyUrl = "https://" + domainName + contextPath + "/multiplePay/callback/sxf";
                    List<DivideAccountsSettingDto> divideAccList =   payOrderMapper.selectDivideSettingDetail(mno,stationId);
//        处理分账
                    String ledgerAccountFlag = "0";
                    if(divideAccList.size()>0 && divideAccList.get(0).getBeginMmo()!=null){
                        ledgerAccountFlag = "1";
                    }
                    resultMap = SXFPayUtil.sxfGoPay(
                            SXFPayParam.builder()
                                    .amt(amt.toString())
                                    .appId(appId)
                                    .mno(mno)
                                    .ordNo(orderNo)
                                    .notifyUrl(notifyUrl)
                                    .subject(subject)
                                    .userId(openId)
                                    .ledgerAccountFlag(ledgerAccountFlag)
                                    .customerIp(multiplePayInfoReq.getCustomerIp())
                                    .ylTrmNo(multiplePayInfoReq.getYlTrmNo())
                                    .userType(payType_num)
                                    .weChatType(weChatType)
                                    .build());
                    break;
                case "5":   //云华支付
                    notifyUrl = "https://" + domainName + contextPath + "/multiplePay/callback/yh";
//                    String   payFor="wx_jsapi";
//                    if("wx".equals(payOrder.getPayType())){
//
//                        if("1".equals(payOrder.getOrderOriginType())){
//                            payFor="wx_minipay";
//                        }
//                        if("2".equals(payOrder.getOrderOriginType())){
//                            payFor="wx_jsapi";
//                        }
//
//                    }else if("zfb".equals(payOrder.getPayType())) {
//                        payFor="";
//                    }
//                    String nowdate= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
//                    resultMap = yunHuaPayUtils.yunHuaPay(YunHuaParam.builder()
//                            .clientOrgCode(payWayList.get(0).getMno())
//                            .lockFlag("lock")
//                            .noticeUrl(notifyUrl)
//                            .partnerCode(payWayList.get(0).getTerminalNo())
//                            .payChannelId(payFor)
//                            .posOrderNo(ordNo)
//                            .reqTime(nowdate)
//                            .txnAmt((BigDecimal.valueOf(Double.valueOf(amt))))
//                            .vsOrderNo(ordNo)
//                            .openId(openId)
//                            .carRefueling(nowdate)
//                            .build());
//                    resultMap.put("payAppId",payAppId);

//                    notifyUrl = "https://" + domainName + contextPath + "/yunHuaNotice";
                    log.info("weChatType{}", weChatType);
                    String txnDesc = "柴油"; // todo
                    switch (payType) {
                        case "zfb":
                            log.info("支付宝拉起支付");
                            resultMap = yunHuaPayUtils.yunHuaPayAli(YunHuaParam.builder()
                                    .partnerCode(payWay1.getMno())
                                    .posOrderNo(orderNo)
                                    .openId(openId)
                                    .noticeUrl(notifyUrl)
                                    .txnDesc(txnDesc)
                                    .miniUrl("www.123.com")
                                    .txnAmt(amt)
                                    .userId(userId)
                                    .build(), payWay1.getSecretKey(), yunhuaPayUrl);
                            p.setClientOrderNo(resultMap.get("clientOrderNo").toString());
                            p.setClientSerialNo(resultMap.get("clientSerialNo").toString());
                            p.setMno(resultMap.get("mno").toString());
                            break;

                        case "wx":
                            if (weChatType.equals("1")) {
                                //小程序
                                log.info("小程序拉起支付");
                                resultMap = yunHuaPayUtils.yunHuaPayWxMini(YunHuaParam.builder()
                                        .partnerCode(payWay1.getMno())
                                        .posOrderNo(orderNo)
                                        .noticeUrl(notifyUrl)
                                        .miniUrl("www.123.com")
                                        .txnAmt(amt)
                                        .userId(userId)
                                        .build(), payWay1.getSecretKey(), yunHuaPrePayUrl);
                                p.setClientOrderNo(resultMap.get("clientOrderNo").toString());
                                p.setClientSerialNo(resultMap.get("clientSerialNo").toString());
                                p.setMno(resultMap.get("mno").toString());
                            } else {
                                log.info("公众号拉起支付");
                                resultMap = yunHuaPayUtils.yunHuaPayV2(YunHuaParam.builder()
                                        .partnerCode(payWay1.getMno())
                                        .posOrderNo(orderNo)
                                        .noticeUrl(notifyUrl)
                                        .txnDesc(txnDesc)
                                        .txnAmt(amt)
                                        .userId(userId)
                                        .build(), payWay1.getSecretKey(), yunHuaPrePayUrl);
                                p.setClientOrderNo(resultMap.get("clientOrderNo").toString());
                                p.setClientSerialNo(resultMap.get("clientSerialNo").toString());
                                p.setMno(resultMap.get("mno").toString());
                            }
                    }
                    resultMap.put("payAppId", payAppId);
                    break;
            }


            resultMap.put("thirdPayment", payTypeSta);
            log.info("返回值{}", resultMap);
            return resultMap;


        } catch (EndingException e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.error("支付失败",e);
            throw new CustomException("支付失败");
        } catch (Exception e) {
            log.error("/toThirdPay-", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new CustomException("支付失败");
        }
    }

    @Override
    public String callbackSxf(Map<String, Object> request) {
        log.info("=====随行付秒杀回调--参数:{}",request);
//        String sign = (String) request.remove("sign");
//        String signContent = RSASignature.getOrderContent(request);
//        if (!RSASignature.doCheck(signContent, sign, SXFPaySign.sxfPublic)) {
//            log.info("=====随行付回调验签失败--参数:{}",request);
//            return SxfCallbackServiceImpl.FAIL_RETURN_VALUE;
//        }
        String ordNo = String.valueOf(request.get("ordNo"));
        if (StringUtils.isBlank(ordNo)) {
            log.info("=====订单号为空");
            return SxfCallbackServiceImpl.SUCCESS_RETURN_VALUE;
        }
        String payTimeStr = String.valueOf(request.get("payTime"));
        LocalDateTime payTime;
        if (StringUtils.isNotBlank(payTimeStr)) {
            try{
                payTime = LocalDateUtils.parseLocalDateTime(payTimeStr,LocalDateTimeUtil.YYYYMMDDHHMMSS);
            }catch (Exception ex){
                log.error(ex.getMessage(),ex);
                payTime = LocalDateTime.now();
            }
        }else{
            payTime = LocalDateTime.now();
        }
        orderCallback(null,ordNo,payTime,false);
        return SxfCallbackServiceImpl.SUCCESS_RETURN_VALUE;
    }

    @Override
    public String callbackYh(Map<String, Object> request) {
        log.info("=====云化秒杀回调--参数:{}",request);
        String ordNo = (String) request.get("clientSerialNo");
        if (StringUtils.isBlank(ordNo)) {
            log.info("=====订单号为空");
            return YunhuaChannel.SUCCESS_RETURN_VALUE;
        }
        String status = String.valueOf(request.get("status"));
        if (!StringUtils.equals("3", status)) {
            log.info("=====云化秒杀回调--状态不对,ordNo:{},status:{}",ordNo,status);
            return YunhuaChannel.SUCCESS_RETURN_VALUE;
        }
        String payTimeStr = String.valueOf(request.get("payTime"));
        LocalDateTime payTime;
        if (StringUtils.isNotBlank(payTimeStr)) {
            try{
                payTime = LocalDateTime.parse(payTimeStr);
            }catch (Exception ex){
                log.error(ex.getMessage(),ex);
                payTime = LocalDateTime.now();
            }
        }else{
            payTime = LocalDateTime.now();
        }
        orderCallback(request,ordNo,payTime,true);
        return YunhuaChannel.SUCCESS_RETURN_VALUE;
    }


    private void orderCallback(Map<String, Object> request,String orderNo,LocalDateTime payTime,boolean yh){
        UnitePayOrder form = new UnitePayOrder();
        form.setUniteOrderNo(orderNo);
        QueryWrapper<UnitePayOrder> qw = Wrappers.query(form);
        qw.last("limit 1");
        UnitePayOrder unitePayOrder = unitePayOrderService.getOne(qw);
        if (unitePayOrder == null) {
            log.info("订单找不到,orderNo:[{}]",orderNo);
            return;
        }
        if (yh) {
            sendSettleInfo(unitePayOrder,request);
        }
        if (!StringUtils.equals("0",unitePayOrder.getStatus())) {
            log.info("订单状态不对,orderNo:[{}],status:[{}]",orderNo,unitePayOrder.getStatus());
            return;
        }
        Station station = enterpriseService.selectStationById(Math.toIntExact(unitePayOrder.getStationId()));
        UnitePayOrderRel orderRel = new UnitePayOrderRel();
        orderRel.setUniteOrderNo(orderNo);
        List<UnitePayOrderRel> list = unitePayOrderRelService.list(Wrappers.query(orderRel));
        UnitePayOrder ud = new UnitePayOrder();
        ud.setId(unitePayOrder.getId());
        ud.setStatus("1");
        ud.setPayTime(payTime);
        if (yh) {
            ud.setTransNo(String.valueOf(request.get("transInfoNo")));
            ud.setPayNo(String.valueOf(request.get("transPayNo")));
        }
        unitePayOrderService.updateById(ud);
        Date payTimeDate = LocalDateTimeUtil.parseDate(payTime);
        for (UnitePayOrderRel unitePayOrderRel : list) {
            PayOrder payOrder = payOrderService.selectOrderInfoByOrdNo(unitePayOrderRel.getOrderNo());
            if (payOrder == null) {
                log.info("消费订单未找到,orderNo:[{}]",unitePayOrderRel.getOrderNo());
                continue;
            }
            if (!StringUtils.equals("0",payOrder.getStatus())) {
                log.info("消费订单状态不对,orderNo:[{}],status:[{}]",orderNo,payOrder.getStatus());
                continue;
            }
            PayOrder udp = new PayOrder();
            udp.setOrderId(payOrder.getOrderId());
            udp.setStatus("1");
            udp.setPayDate(payTimeDate);
            udp.setUnitePayOrderNo(unitePayOrder.getUniteOrderNo());
            udp.setPayWayId(Math.toIntExact(unitePayOrder.getPayWayId()));
            if (StringUtils.equals("0",payOrder.getChannelFeePayer())) {
                // 司机承担渠道费
                if (station != null && station.getIsShowSaasAmtCommission() == 0) {
                    // 后台订单列表不展示渠道费
                    BigDecimal recAmt = payOrder.getReceivableAmt() == null ? BigDecimal.ZERO : BigDecimal.valueOf(payOrder.getReceivableAmt());
                    BigDecimal disAmt = payOrder.getDiscountAmt() == null ? BigDecimal.ZERO : BigDecimal.valueOf(payOrder.getDiscountAmt());
                    BigDecimal couAmt = payOrder.getDiscountCouponAmt() == null ? BigDecimal.ZERO : BigDecimal.valueOf(payOrder.getDiscountCouponAmt());
                    BigDecimal amt1 = recAmt.subtract(disAmt).subtract(couAmt);
                    if (amt1.compareTo(BigDecimal.ZERO)<=0) {
                        amt1 = DecimalConstant.O_01;
                    }
                    udp.setActualAmt(BigDecimal.valueOf(payOrder.getAmt()));
                    udp.setAmt(amt1.doubleValue());
                }
            }
            payOrderService.updateByPrimaryKeySelective(udp);
            payOrder.setPayDate(payTimeDate);
            gzhNewsTemplateService.feiePush(payOrder);
            // 微信模板通知-支付成功（加油成功）通知
            AppUserInfo appUserInfo = appUserInfoService.getById(payOrder.getConsumerId());
            if (appUserInfo != null && StringUtils.isNotBlank(appUserInfo.getBlogOpenid()) ) {
                Map<String, String> templateParams = new HashMap<>();
                templateParams.put("openid", appUserInfo.getBlogOpenid());
                templateParams.put("stationName", payOrder.getStationName());
                templateParams.put("oilName", payOrder.getOilName());
                //获取用户电子会员卡信息
                BigDecimal dzkBalance = BigDecimal.ZERO;
                if (!MobilePhoneUtil.isFakePhone(appUserInfo.getMobilePhone()) && ObjectUtils.isNotEmpty(payOrder.getCardType())) {
                    CustomerElectronicCard cardInfo = electronicMembershipCardService.getCustomerElectronicCard(appUserInfo, payOrder.getCardType(), station);
                    if (cardInfo != null) {
                        dzkBalance = cardInfo.getTotalAmt();
                    }
                }
                templateParams.put("payDetail", "实付" + payOrder.getAmt() + "元，积分+0");
                templateParams.put("walletBalance", dzkBalance.toString() + "元");
                log.info("微信支付-微信模板参数：{}", templateParams);
                wxPushUtil.sendTemplateMsg(payOrder.getEnterpriseId(), templateParams, WxTemplateEnum.REFUEL_SUCCESS);
            }
        }
    }

    private void sendSettleInfo(UnitePayOrder unitePayOrder,Map<String, Object> request){
        PhysicalCardBalance pcb = new PhysicalCardBalance();
        pcb.setStationId(String.valueOf(unitePayOrder.getStationId()));
        pcb.setPayWayId(unitePayOrder.getPayWayId());
        pcb.setAmount(unitePayOrder.getAmt());
        pcb.setBalanceNo(unitePayOrder.getUniteOrderNo());
        gzhNewsTemplateService.sendStkSettleInfo(pcb,request);
    }

}
